package ssi.staaar.ciphers;

import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

import encoders.Base64;

public class SymCipher {
	private SecretKey SKey;
	private byte[] initVector = new byte[] { 0x10, 0x10, 0x01, 0x04, 0x01, 0x01, 0x01, 0x02,  0x10, 0x10, 0x01, 0x04, 0x01, 0x01, 0x01, 0x02 };
	private AlgorithmParameterSpec algParamSpec = new IvParameterSpec(initVector);
	private int sessionId=0;
	
	public String crypt(String plaintext) throws Exception{
		return crypt(plaintext, SKey);
	}

	public String crypt(String plaintext, Key key) throws Exception {
		byte[] cipherTextBytes = null;
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		cipher.init(Cipher.ENCRYPT_MODE, SKey, algParamSpec);
		cipherTextBytes = Base64.encode(cipher.doFinal(plaintext.getBytes()));
		String cipherText = new String(cipherTextBytes);
		return cipherText;
	}
	
	public String decrypt(String ciphertext) throws Exception {
		return decrypt(ciphertext, SKey);
	}

	public String decrypt(String ciphertext, Key key) throws Exception {
		byte[] cipherTextBytes = Base64.decode(ciphertext.getBytes());
		byte[] plainTextBytes = null;
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		cipher.init(Cipher.DECRYPT_MODE, SKey, algParamSpec);
		plainTextBytes = cipher.doFinal(cipherTextBytes);
		String plainText = new String(plainTextBytes, "UTF8");
		return plainText;
	}
	
	public void generateKey() throws NoSuchAlgorithmException {
		SKey =  KeyGenerator.getInstance("AES").generateKey();	
	}
	
	public SecretKey getKey(){
		return SKey;
	}

	public int getSessionId() {
		return sessionId;
	}

	public void setSessionId(int sessionId) {
		this.sessionId = sessionId;
	}

	public void setKey(String skey){
		byte[] keyenc=Base64.decode(skey.getBytes());
		this.SKey=new SecretKeySpec(keyenc, "AES");
		//sta cosa qua sotto non mi piace molto a sto punto mi potrei salva la key in byte[]? boh vedremo
		//byte[] raw = SKey.getEncoded();
		//SKeySpec = new SecretKeySpec(raw, "AES");
	}
	
	public void setKey(SecretKey sessionKey) {
		this.SKey=sessionKey;
	}
	
	//utility methods for session key
	public static SecretKey stringToKey(String key){
		return new SecretKeySpec(Base64.decode(key.getBytes()), "AES");
	}
	
	public static String keyToString(SecretKey key){
		return new String(Base64.encode(key.getEncoded()));
	}

	public void setPasswordAsKey(String key) {
		MessageDigest digester;
		try {
			digester = MessageDigest.getInstance("MD5");

			char[] password = key.toCharArray();
			for (int i = 0; i < password.length; i++) {
				digester.update((byte) password[i]);
			}
			byte[] passwordData = digester.digest();

			SKey = new SecretKeySpec(passwordData, "AES");
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}